using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;

using ADODB;
using Microsoft.CommerceServer.Interop.Catalog;

namespace CatalogMigration
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class frmCatalogMigrationTool : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Button btnDataSource;

		internal static CatalogManager catalogMgr;
		internal static string ctlgName;
		internal static bool ctlgNew = false;
		internal static string categoryTable;
		internal static string productTable;
		internal static string ConStr;
		internal static string productField;
		internal static string categoryField;
		private ProductCatalog prodCtlg;
		private string ConsumerServer;
		private string ConsumerDatabase;
		private System.Windows.Forms.Button btnCatalogManager;
		private System.Windows.Forms.Button btnProduct;
		private System.Windows.Forms.Button btnCategory;
		private System.Windows.Forms.Button btnRelation;
		private System.Windows.Forms.Button button1;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public frmCatalogMigrationTool()
		{
			InitializeComponent();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.btnDataSource = new System.Windows.Forms.Button();
			this.btnCatalogManager = new System.Windows.Forms.Button();
			this.btnProduct = new System.Windows.Forms.Button();
			this.btnCategory = new System.Windows.Forms.Button();
			this.btnRelation = new System.Windows.Forms.Button();
			this.button1 = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// btnDataSource
			// 
			this.btnDataSource.Location = new System.Drawing.Point(8, 8);
			this.btnDataSource.Name = "btnDataSource";
			this.btnDataSource.Size = new System.Drawing.Size(344, 23);
			this.btnDataSource.TabIndex = 0;
			this.btnDataSource.Text = "Select Data Source";
			this.btnDataSource.Click += new System.EventHandler(this.btnDataSource_Click);
			// 
			// btnCatalogManager
			// 
			this.btnCatalogManager.Location = new System.Drawing.Point(8, 32);
			this.btnCatalogManager.Name = "btnCatalogManager";
			this.btnCatalogManager.Size = new System.Drawing.Size(344, 23);
			this.btnCatalogManager.TabIndex = 1;
			this.btnCatalogManager.Text = "Load Catalog Manager\\Select Target";
			this.btnCatalogManager.Click += new System.EventHandler(this.btnCatalogManager_Click);
			// 
			// btnProduct
			// 
			this.btnProduct.Location = new System.Drawing.Point(8, 56);
			this.btnProduct.Name = "btnProduct";
			this.btnProduct.Size = new System.Drawing.Size(344, 23);
			this.btnProduct.TabIndex = 2;
			this.btnProduct.Text = "Select Product Migration Table";
			this.btnProduct.Click += new System.EventHandler(this.btnMigrationTables_Click);
			// 
			// btnCategory
			// 
			this.btnCategory.Location = new System.Drawing.Point(8, 80);
			this.btnCategory.Name = "btnCategory";
			this.btnCategory.Size = new System.Drawing.Size(344, 23);
			this.btnCategory.TabIndex = 3;
			this.btnCategory.Text = "Select Category Migration Table";
			this.btnCategory.Click += new System.EventHandler(this.btnCategory_Click);
			// 
			// btnRelation
			// 
			this.btnRelation.Location = new System.Drawing.Point(8, 104);
			this.btnRelation.Name = "btnRelation";
			this.btnRelation.Size = new System.Drawing.Size(344, 23);
			this.btnRelation.TabIndex = 4;
			this.btnRelation.Text = "Relate Categories to Products";
			this.btnRelation.Click += new System.EventHandler(this.btnRelation_Click);
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(8, 128);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(344, 23);
			this.button1.TabIndex = 5;
			this.button1.Text = "Migrate Data";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// frmCatalogMigrationTool
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(360, 159);
			this.Controls.Add(this.button1);
			this.Controls.Add(this.btnRelation);
			this.Controls.Add(this.btnCategory);
			this.Controls.Add(this.btnProduct);
			this.Controls.Add(this.btnCatalogManager);
			this.Controls.Add(this.btnDataSource);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
			this.MaximizeBox = false;
			this.Name = "frmCatalogMigrationTool";
			this.Text = "Simple Catalog Migration Tool";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Tools.Log(@"[Info] Starting Migration...");
			Application.Run(new frmCatalogMigrationTool());
		}

		private void btnDataSource_Click(object sender, System.EventArgs e)
		{
			try
			{
				// set data source
				object objdl = promptForDataSource();
			
				// if the user selects cancel then don't execute anything 
				if(objdl!=null)
				{
					ConStr = ((ADODB.Connection)objdl).ConnectionString.Replace("Provider=SQLOLEDB.1;","");

					// get the server name and database
					ConsumerServer = ((ADODB.Connection)objdl).Properties["Data Source"].Value.ToString();
					ConsumerDatabase = ((ADODB.Connection)objdl).Properties["Initial Catalog"].Value.ToString();
				}

				Tools.Log(@"[Pass] Created a UDL");
			}
			catch(Exception ex)
			{
				// log the exception
				Tools.Log(@"[Fail] Error while creating a UDL", ex);
			}
		}

		private void btnCatalogManager_Click(object sender, System.EventArgs e)
		{
			try
			{
				// first select catalog database
				object objdl = promptForDataSource();
			
				// if the user selects cancel then don't execute anything 
				if(objdl!=null)
				{
					string constring = ((ADODB.Connection)objdl).ConnectionString;

					// create a dummy object for full text catalogs to create
					object dummy = new object();
					dummy = 0;

					catalogMgr = new CatalogManagerClass();
					catalogMgr.Initialize(constring, true, dummy);
					Tools.Log(@"[Pass] Initialized Catalog Manager");

					// allow the user to select a catalog or create a new one.
					frmCatalogSelection ctlg = new frmCatalogSelection();
					DialogResult result = ctlg.ShowDialog(this);
				}
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while Initializing CatalogManager", ex);
			}
		}

		private object promptForDataSource()
		{
			MSDASC.DataLinks dl = new MSDASC.DataLinksClass();
			object adoCon = new ADODB.Connection();
			((ADODB.Connection)adoCon).ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Data Source=(local)";
			
			object objdl = dl.PromptEdit(ref adoCon);
			return objdl;
		}

		private void btnMigrationTables_Click(object sender, System.EventArgs e)
		{
			// for this sample allow the user to select two tables one has the Categories
			// and another has the products
			frmMigrationTables migrationTables = new frmMigrationTables("Products");
			migrationTables.ShowDialog(this);
		}

		private void btnCategory_Click(object sender, System.EventArgs e)
		{
			// for this sample allow the user to select two tables one has the Categories
			// and another has the products
			frmMigrationTables migrationTables = new frmMigrationTables("Categories");
			migrationTables.ShowDialog(this);
		}

		private void btnRelation_Click(object sender, System.EventArgs e)
		{
			Relation relation = new Relation();
			relation.ShowDialog(this);
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			// migrated data
			// create Category Definition
			CreateDefiniton("Product", productTable);
			// add properties to defintions
			try
			{
				string SQLString = "SELECT * FROM "+productTable;
				SqlConnection sqlcon = new SqlConnection(ConStr);
				sqlcon.Open();
				SqlDataAdapter ad = new SqlDataAdapter(SQLString, sqlcon);
				DataSet ds = new DataSet();
				ad.Fill(ds);

				// we just need the rows
				AddDefinitionProperty(ds.Tables[0].Rows[0], productTable);
				
				sqlcon.Close();
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while creating products", ex);
			}
			
			// see if we have to create a catalog or use an existing one
			if(ctlgNew)
			{
				prodCtlg = createCatalog();
			}
			else
			{
				// make sure that the ProductID and VariantID matches
				prodCtlg = catalogMgr.GetCatalog(ctlgName);
			}

			// create Product Definition
			CreateDefiniton("Category", categoryTable);

			// create Categories
			try
			{
				string SQLString = "SELECT * FROM "+categoryTable;
				SqlConnection sqlcon = new SqlConnection(ConStr);
				sqlcon.Open();
				SqlDataAdapter ad = new SqlDataAdapter(SQLString, sqlcon);
				DataSet ds = new DataSet();
				ad.Fill(ds);

				// add category defintion
				AddDefinitionProperty(ds.Tables[0].Rows[0], categoryTable);

				// create categories
				foreach(DataRow dr in ds.Tables[0].Rows)
				{
					CreateCategory(dr);
				}

				sqlcon.Close();
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while creating categories", ex);
			}

			// create Products
			try
			{
				string SQLString = "SELECT * FROM "+productTable;
				SqlConnection sqlcon = new SqlConnection(ConStr);
				sqlcon.Open();
				SqlDataAdapter ad = new SqlDataAdapter(SQLString, sqlcon);
				DataSet ds = new DataSet();
				ad.Fill(ds);

				foreach(DataRow dr in ds.Tables[0].Rows)
				{
					CreateProduct(dr);
				}

				sqlcon.Close();
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while creating products", ex);
			}
		}

		private ProductCatalog createCatalog()
		{
			try
			{
				// Create a catalog
				// I am going to cheat as I know the productID is ProdID
				return catalogMgr.CreateCatalog(ctlgName, "ProdID", null, "1033", "USD", "lbs", DateTime.Now.ToString(), DateTime.Now.ToString(), "en-US", "en-US", false);
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while creating catalog", ex);
			}

			return null;
		}

		private void CreateDefiniton(string type, string defintionName)
		{
			switch(type)
			{
				case "Product":
					catalogMgr.CreateProductDefinition(defintionName);
					break; 
				case "Category":
					catalogMgr.CreateCategoryDefinition(defintionName);
					break;
			}
		}

		private void AddDefinitionProperty(DataRow dr, string definitionName)
		{
			CatalogDataTypeEnum csDataType = CatalogDataTypeEnum.cscInvalid;
			object MaxLen = new object();

			// loop through the columns
			foreach(DataColumn dc in dr.Table.Columns)
			{
				GetCommerceDataType(dc, ref csDataType, ref MaxLen);
				string propertyName = dc.ColumnName;
				switch(propertyName)
				{
					case "ProductID":
						propertyName = "ProdID";
						break;
				}
				try
				{
					catalogMgr.CreateProperty(propertyName, csDataType, MaxLen);
				}
				catch(Exception ex)
				{
					// we may have dupes here so do nothing and try to add definition.
				}
				try
				{
					catalogMgr.AddDefinitionProperty(definitionName, propertyName);
				}
				catch(Exception ex)
				{
					//
				}
			}
		}

		private void CreateCategory(DataRow dr)
		{
			try
			{
				Category cat = catalogMgr.GetCatalog(ctlgName).CreateCategory(categoryTable, dr["CategoryID"].ToString(), null, null);
				ADODB._Recordset rs = cat.GetCategoryProperties;
				rs.Fields[""].Value = dr["CategoryName"].ToString();
				cat.SetCategoryProperties(rs, true);
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while creating category", ex);
			}
		}

		private void CreateProduct(DataRow dr)
		{
			try
			{
				//
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while creating product", ex);
			}
		}

		private void GetCommerceDataType(DataColumn dc, ref CatalogDataTypeEnum CatalogType, ref object MaxLen)
		{
			try
			{
				switch(dc.DataType.Name)
				{
					case "bit":
						CatalogType = CatalogDataTypeEnum.cscInteger;
						MaxLen = (object)"10";
						break;
					case "Int32":
						CatalogType = CatalogDataTypeEnum.cscInteger;
						MaxLen = (object)"10";
						break;
					case "Decimal":
						CatalogType = CatalogDataTypeEnum.cscDouble;
						if(dc.MaxLength==-1)
						{
							MaxLen = (object)"10";
						}
						else
						{
							MaxLen = (object)dc.MaxLength;
						}
						break;
					case "char":
						CatalogType = CatalogDataTypeEnum.cscString;
						MaxLen = (object)dc.MaxLength;
						break;
					case "varchar":
						CatalogType = CatalogDataTypeEnum.cscString;
						MaxLen = (object)dc.MaxLength;
						break;
					case "Text":
						CatalogType = CatalogDataTypeEnum.cscText;
						MaxLen = (object)null;
						break;
					case "smallint":
						CatalogType = CatalogDataTypeEnum.cscInteger;
						MaxLen = (object)"10";
						break;
					case "datetime":
						CatalogType = CatalogDataTypeEnum.cscDateTime;
						MaxLen = (object)"20";
						break;
					case "String":
						CatalogType = CatalogDataTypeEnum.cscText;
						MaxLen = (object)dc.MaxLength;
						break;
				}
			}
			catch(Exception ex)
			{
				Tools.Log(@"[Fail] Error while getting Commerce Data Type", ex);
				// set defaults
				CatalogType = CatalogDataTypeEnum.cscInvalid;
				MaxLen = (object)null;
			}
		}
	}
}
